#ifndef _RUNTIME_H_JM_20110828_
#define _RUNTIME_H_JM_20110828_

#include "bobox_runtime.hpp"

#include "../boxes/InputReaderBox.h"
#include "../boxes/OutputWriterBox.h"
#include "../boxes/ForkBox.h"
#include "../boxes/SpliceBox.h"
#include "../boxes/JoinBox.h"

#include "../boxes/FlowBox.h"
#include "../boxes/CrossBox.h"
#include "../boxes/HelloBox.h"

#include "../boxes/input/HardCodedDataInputBox.h"
#include "../boxes/output/ConsoleWriterBox.h"
#include "../boxes/operation/OperationBox.h"
#include "../boxes/operation/AdditionBox.h"

#include "../table/JoinContext.h"
#include "../table/MultiTypeTable.h"

#include "BoxCreatorRegistrator.h"
#include "BoxParameterPack.h"

#include <sstream>

namespace jm4bbx {


class results : public bobox::results {
	virtual size_t get_tables_count() const { return 0; }
	virtual size_t get_rows_count(size_t table) const { return 0; }		
	virtual void get_rows(size_t table, size_t from, size_t count, rows_type &rows) const { }
};

class request : public bobox::request {
public:
	request(bobox::request_id_type rqid, bobox::runtime *rt, bobox::box_model *model)
		: bobox::request(rqid, rt, model) { }
	virtual const bobox::results *get_results() const { return &results_; }
private:
	results results_;
};


class runtime : public bobox::runtime {
public:
    //void createTables(const size_t rows1, const size_t rows2) {        
    //    const size_t COLS_1 = 5;
    //    const size_t KEY_1 = 2;        
    //    initTable(rows1, COLS_1, KEY_1, inputTables_.table1_);
    // //   print(inputTables_.table1_);
    //    const size_t COLS_2 = 2;
    //    const size_t KEY_2 = 0;
    //    initTable(rows2, COLS_2, KEY_2, inputTables_.table2_);
    //   // print(inputTables_.table2_);
    //}
private:
    
   // MultiTypeTable t1, t2, table;

    

    //typedef int JoinColumnType;

    //InputTablesContext<JoinColumnType> inputTables_;


    //void addLine(MultiTypeTable<JoinColumnType>::CellContainer& cells, const size_t line, const size_t columns, 
    //    size_t keyIndex, MultiTypeTable<JoinColumnType>::CellType& keyVal) {
    //            
    //            for (size_t i = 0; i < columns; ++i) {
    //                if (i == keyIndex) {
    //                    cells.push_back(keyVal);
    //                }
    //                else {
    //                    std::stringstream str;                
    //                   // str << "Col " << i << " Line " << line;
    //                    str << "C" << i << "L" << line;
    //                    cells.push_back(str.str());
    //                }
    //            }            

    //}

    //void initTable(const size_t rows, const size_t cols, const size_t keyIndex,
    //     MultiTypeTable<JoinColumnType>& table) {
    //        
    //        MultiTypeTable<JoinColumnType>::ColumnContainer data;
    //        for (size_t i = 0; i < rows; ++i) {
    //            MultiTypeTable<JoinColumnType>::CellContainer row;
    //            std::stringstream str;
    //            if (i == 6) {
    //                addLine(row, i, cols, keyIndex, std::string("3"));
    //            }
    //            else {
    //                str << i;
    //                addLine(row, i, cols, keyIndex, str.str());
    //            }
    //            data.push_back(row);
    //        }

    //        table.setKeyColumnIndex(keyIndex);
    //        table.setTable(data);
    //}


    //static void print(const MultiTypeTable<JoinColumnType>& t) {
    //    for (size_t i = 0; i < t.size(); ++i) {
    //        OutputWriterBox<JoinColumnType>::print(t.getLine(i));
    //    }
    //    std::cout << std::endl;
    //}



    

    virtual void init_impl(const bofe::configuration &conf) { }



	virtual void destroy_impl() { }

	virtual bobox::request* create_request_impl(const std::string &model, bobox::request_id_type rqid) {
		return new request(rqid, this, 
            new bobox::model_box_model(bobox::box_model_id_type(0), 
                bobox::box_tid_type("model_box"), model, this));
	}

	virtual bobox::box_model_ptr_type create_box_model_impl(bobox::box_model_id_type id, 
        bobox::box_tid_type tid, const bobox::parameters &params) {
		
        
		    //if (tid == bobox::box_tid_type("Source")) {
			   // 
      //          return bobox::box_model_ptr_type(new input_reader_box<JoinColumnType>::model(id, tid, this, params, &inputTables_));
      //          /*return bobox::box_model_ptr_type(
      //              new ColumnForkBox<JoinColumnType>::model(
      //                  id, tid, this, params, &inputTables_));*/
      //      }
      //      else if (tid == bobox::box_tid_type("Destination")) {
			   // return bobox::box_model_ptr_type(new output_writer_box::model(id, tid, this, params));
      //      }
      //      else

			//if (tid == bobox::box_tid_type("FlowBox")) {
			//	return bobox::box_model_ptr_type(
			//		new FlowBox::model(id, tid, this, params));
			//}
			//else if (tid == bobox::box_tid_type("Input")) {
			//    return bobox::box_model_ptr_type(
   //                 new InputReaderBox<JoinColumnType>::model(id, tid, this, params, &inputTables_));
   //         }
		 //   else if (tid == bobox::box_tid_type("Fork")) {
			//    return bobox::box_model_ptr_type(new ForkBox::model(id, tid, this, params));
   //         }
   //         else if (tid == bobox::box_tid_type("Output")) {
			//    return bobox::box_model_ptr_type(
   //                 new OutputWriterBox<JoinColumnType>::model(id, tid, this, params, &inputTables_));
   //         }
   //         else if (tid == bobox::box_tid_type("Join")) {
			//    return bobox::box_model_ptr_type(new JoinBox::model(id, tid, this, params));
   //         }
			//else if (tid == bobox::box_tid_type("Cross")) {
			//	return bobox::box_model_ptr_type(new CrossBox::BoxModel(id, tid, this, params));
			//}
			//else 
				if (tid == bobox::box_tid_type("Hello")) {
				return bobox::box_model_ptr_type(new HelloBox::BoxModel(BoxParameterPack(id, tid, this, params)));
			}
			//else if (tid == bobox::box_tid_type("I")) {
			//	return bobox::box_model_ptr_type(new HardCodedDataInputBox::BoxModel(id, tid, this, params));
			//}
			//else if (tid == bobox::box_tid_type("O")) {
			//	return bobox::box_model_ptr_type(new ConsoleWriterBox::BoxModel(id, tid, this, params));
			//}
			//else if (tid == bobox::box_tid_type("A")) {
			//	return bobox::box_model_ptr_type(new Operation<Addition>::BoxModel(id, tid, this, params));
			//}

			const std::string& rtid = tid;
			if (BoxCreatorRegistrator::getInstance()->isRegistered(rtid)) {
				return BoxCreatorRegistrator::getInstance()->getCreator(rtid
					)->createBox(id, tid, this, params);
			}
            assert("Neznamy typ boxu!" && false);
			return nullptr;
	}

	virtual bobox::type_descriptor_ptr_type create_type_descriptor_impl(bobox::type_tid_type tid, 
        const bobox::parameters &params)
	{
		if (tid == bobox::type_tid_type("int"))
			return bobox::type_descriptor_ptr_type(new bobox::generic_type_descriptor<bobox::int_policy>());
		if (tid == bobox::type_tid_type("string"))
			return bobox::type_descriptor_ptr_type(new bobox::generic_type_descriptor<bobox::string_policy>());
		assert(false);
		return nullptr;
	}
};

} // namespace jm4bbx

#endif
